package org.yunai.swjg.server.module.item.operation.use;

import org.yunai.swjg.server.core.constants.SysMessageConstants;
import org.yunai.swjg.server.module.item.container.ShoulderBag;
import org.yunai.swjg.server.module.item.template.ItemTemplate;
import org.yunai.swjg.server.module.item.vo.Item;
import org.yunai.swjg.server.module.player.vo.Player;
import org.yunai.swjg.server.rpc.message.S_C.S_C_SysMessageReq;

import java.util.List;

/**
 * 使用道具实现基类
 * User: yunai
 * Date: 13-6-2
 * Time: 下午2:09
 */
public abstract class AbstractItemUseOperation implements ItemUseOperation {

    /**
     * 判断是否能够使用<br />
     * 以下操作会导致无法使用：
     * <pre>
     *     1. 道具为空
     *     2. 道具无法使用
     *     3. 使用操作不合适
     *     4. 玩家等级不够。该情况会发送消息
     *     5. 子类实现判断是否可以使用{@link #canUseImpl(org.yunai.swjg.server.module.player.vo.Player, org.yunai.swjg.server.module.item.vo.Item, int, int)}
     * </pre>
     *
     * @param player   玩家信息
     * @param item     道具
     * @param targetId 目标编号
     * @param param    拓展参数
     * @return 是否能够使用
     */
    private boolean canUse(Player player, Item item, int targetId, int param) {
        if (Item.isEmpty(item)) { // 空道具无法使用
            return false;
        }
        if (!item.getTemplate().isCanUse()) { // 道具是可以使用的
            return false;
        }
        if (!isSuitable(player, item, targetId)) { // 不适合当前操作
            return false;
        }
        // 验证玩家等级
        if (player.getLevel() < item.getTemplate().getNeedLevel()) {
            player.message(new S_C_SysMessageReq(SysMessageConstants.ITEM_USE_LEVEL_NOT_ENOUGH));
            return false;
        }
        return canUseImpl(player, item, targetId, param); // 子类验证是否能够使用
    }

    /**
     * 子类实现判断是否能够使用
     *
     * @param player   玩家信息
     * @param item     道具
     * @param targetId 目标编号
     * @param param    拓展参数
     * @return 是否能够使用
     */
    protected abstract boolean canUseImpl(Player player, Item item, int targetId, int param);

    @Override
    public boolean use(Player player, Item item, int targetId, int param) {
        return canUse(player, item, targetId, param) && useImpl(player, item, targetId, param);
    }

    /**
     * 子类实现使用，并返回操作结果
     *
     * @param player   玩家信息
     * @param item     道具
     * @param targetId 目标编号
     * @param param    拓展参数
     * @return 使用结果
     */
    protected abstract boolean useImpl(Player player, Item item, int targetId, int param);

    /**
     * 使用道具，并返回还有多少没使用掉。
     *
     * @param bag         背包
     * @param templateId  使用道具编号
     * @param count       使用道具数量
     * @param changedList 修改的道具数组
     * @return 剩余未使用的道具数量
     */
    protected final int consumeItem(ShoulderBag bag, int templateId, int count, List<Item> changedList) {
        int ownCount = bag.getCountByTemplateId(templateId);
        if (ownCount != 0) {
            if (ownCount >= count) {
                changedList.addAll(bag.removeItem(ItemTemplate.getItemTemplate(templateId), count));
                count = 0;
            } else {
                changedList.addAll(bag.removeItem(ItemTemplate.getItemTemplate(templateId), ownCount));
                count -= ownCount;
            }
        }
        return count;
    }
}